package com.zmzncs.lmtc.module.order.controller;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.databind.JsonNode;
import com.zmzncs.lmtc.common.annotation.Idempotent;
import com.zmzncs.lmtc.common.pojo.CurrOrderRes;
import com.zmzncs.lmtc.common.pojo.PageVO;
import com.zmzncs.lmtc.common.pojo.Rest;
import com.zmzncs.lmtc.common.pojo.bolian.*;
import com.zmzncs.lmtc.common.util.*;
import com.zmzncs.lmtc.common.websocket.WebsocketUtil;
import com.zmzncs.lmtc.module.customer.pojo.card.RechargeForm;
import com.zmzncs.lmtc.module.customer.service.CardService;
import com.zmzncs.lmtc.module.order.pojo.order_info.*;
import com.zmzncs.lmtc.module.order.service.OrderInfoService;
import io.micrometer.core.instrument.util.StringUtils;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import java.util.*;


/**
 * <p>
 * 客户-信息 前端控制器
 * </p>
 *
 * @author 任建波
 * @since 2020-09-01
 */
@Api(tags = "订单管理")
@RestController
@RequestMapping("/order/orderInfo")
@Validated
@Slf4j
public class OrderInfoController {

    @Autowired
    OrderInfoService orderInfoService;
    @Autowired
    CardService cardService;
    @Autowired
    WebsocketUtil websocketUtil;
    @Autowired
    HttpServletRequest  request;

    @ApiOperation(value = "查询客户当前车辆在停车场情况")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "token", value = "请求头token", required = true),
    })
    @GetMapping(value = "/getCustomerCarParkList")
    public Rest<List<OrderInfoParkCarVO>> getCustomerCarParkList() {
        List<OrderInfoDTO> customerParkCar = orderInfoService.getCustomerCarParkList();
        List<OrderInfoParkCarVO> orderInfoParkCarVOList = JsonUtil.listTransform(customerParkCar, OrderInfoParkCarVO.class);
        return RestUtil.success(orderInfoParkCarVOList);
    }

    @ApiOperation(value = "查询客户订单")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "token", value = "请求头token", required = true),
    })
    @PostMapping(value = "/getCustomerOrderPage")
    public Rest<PageVO<OrderInfoVO>> getCustomerOrderPage(@RequestBody UserOrderInfoForm form) {
        IPage<OrderInfoDTO> customerOrderPage = orderInfoService.getCustomerOrderPage(form);

        PageVO<OrderInfoVO> orderInfoVOPageVO = JsonUtil.pageTransform(customerOrderPage, OrderInfoVO.class);
        return RestUtil.success(orderInfoVOPageVO);
    }

    @ApiOperation(value = "查询车主实时订单")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "token", value = "请求头token", required = true),
    })
    @GetMapping(value = "queryCurrOrder")
    public Rest<List<OrderInfoCurrentVO>> queryCurrOrder(@RequestParam String list) {
        List<OrderInfoCurrentVO> orderInfoCurrentVOList = new ArrayList<>();

        JSONArray jsonArray = JSONArray.parseArray(list);
        List<OrderInfoCurrOrderForm> infoCurrOrderList = JSONObject.parseArray(jsonArray.toJSONString(), OrderInfoCurrOrderForm.class);

        //  处理订单数据
        for(OrderInfoCurrOrderForm currOrder: infoCurrOrderList){
            //  查询实时订单
            CurrOrderRes currOrderRes = orderInfoService.queryCurrOrder(currOrder.getOrderCode(), currOrder.getCarNumber(), currOrder.getParkId());

            OrderInfoCurrentVO orderInfoCurrentVO = new OrderInfoCurrentVO();
            orderInfoCurrentVO.setCarCardNum(currOrderRes.getPlate_number()); //  车牌号
            orderInfoCurrentVO.setCarInTime(new Date(currOrderRes.getStart_time()*1000L));    //  进场时间
            orderInfoCurrentVO.setDesc(currOrderRes.getErrmsg());   //  描述
            orderInfoCurrentVO.setOrderCode(currOrder.getOrderCode()); //  订单号
            orderInfoCurrentVO.setParkName(currOrderRes.getPark_name());  //  停车场名称
            orderInfoCurrentVO.setFreeOutTime(currOrderRes.getFree_out_time());   //  预付后免费出场时长（分钟）
            orderInfoCurrentVO.setCannotPrePayReason(currOrderRes.getErrmsg()); //  不能预支付原因
            orderInfoCurrentVO.setParkSource(currOrderRes.getParkSource()); //  停车场来源
            orderInfoCurrentVO.setMoney(currOrderRes.getMoney() == null ? "0" : currOrderRes.getMoney()); //  应付金额
            orderInfoCurrentVO.setDuration(currOrderRes.getDuration() == null ? 0 : currOrderRes.getDuration());   //  停车时长（分钟）
            orderInfoCurrentVO.setCardType(currOrderRes.getCardType());
            orderInfoCurrentVO.setCardTypeMsg(currOrderRes.getCardTypeMsg());

            orderInfoCurrentVOList.add(orderInfoCurrentVO);
        }

        return RestUtil.success(orderInfoCurrentVOList);
    }

    @ApiOperation(value = "泊链请求查询道尔、盒子等的实时订单")
    @PostMapping(value = "getParkCurrOrder")
    public BolianParkCurrOrderRes getParkCurrOrder(@RequestBody String params) {

        BolianParkCurrOrderRes bolianParkCurrOrderRes = orderInfoService.getParkCurrOrder(params);

        return bolianParkCurrOrderRes;
    }

    @ApiOperation(value = "车辆进场通知")
    @PostMapping(value = "carInPark")
    @Idempotent
    public Map<String,Object> carInPark(@RequestBody String data) {
        /**
         * 1、如果车辆已经上传泊链入场信息，则泊链将不会再次通知中萌入场信息
         * 2、如果车牌没有绑定立码停车，则不上传入场信息到泊链
         * 3、连续4天支付是指每天会在车场的第1笔支付中取一个地址，取一个用户的地址，然后4天的数据出来之后，会没比对每两个地址之间的距离，如果精度都小于50米的话，就认为定位是正确的，就会更新车场的数据
         * 4、车主与车场union_id相同，则不通知
         * */

        Map<String, Object> map = orderInfoService.carInPark(data);

        /*发送socket进场通知*/
        if(map.get("customerId") != null){
            websocketUtil.sendMessage(map.get("customerId").toString(), "car-in-park@" + map.get("carNumber"));
        }

        return map;
    }

    @ApiOperation(value = "预支付")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "token", value = "请求头token", required = true),
            @ApiImplicitParam(paramType = "query", name = "orderCode", value = "订单号", required = true),
    })
    @PostMapping(value = "prePayCurrOrder")
    public Rest<PrePayCurrOrderVO> prePayCurrOrder(@NotNull String orderCode) {
        /**非泊链会员不可以预支付，部分泊链停车场可以预支付*/

        BolianPrePayRes bolianPrePayRes = orderInfoService.prePayCurrOrder(orderCode);

        if(bolianPrePayRes.getState().equals(1)){
            return RestUtil.success(bolianPrePayRes);
        } else {
            return RestUtil.warning(bolianPrePayRes.getErrmsg());
        }
    }

    @ApiOperation(value = "泊链停车场预支付通知")
    @PostMapping(value = "prePayOrderNotice")
    public Map<String, Object> prePayOrderNotice(@RequestBody String data) {
        Map map = orderInfoService.prePayOrderNotice(data);

        return map;
    }

    @ApiOperation(value = "非泊链停车场预支付通知")
    @PostMapping(value = "noBolianPrePayNotice")
    public Map<String, Object> noBolianPrePayNotice(@RequestBody String data) {
        JsonNode jsonNode = JsonUtil.getJsonNode(data);
        String dataStr = jsonNode.get("data").toString();

        //  通知中萌数据（客户向泊链停车场支付）
        BoLianPrePayOrderDataForm zmFormData = JSONObject.parseObject(dataStr, BoLianPrePayOrderDataForm.class, Feature.OrderedField);

        Map<String,Object> map = new HashMap();
        map.put("order_id", zmFormData.getOrder_id());    //  订单记录号(车辆在停车场停车唯一订单编号，对应入场订单编号)
        map.put("trade_no", zmFormData.getTrade_no());    //  交易单号（电子支付对账）
        map.put("state", 1);
        map.put("prepay", zmFormData.getPrepay());

        return map;
    }

    @ApiOperation(value = "查询订单是否支付成功")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "orderCode", value = "订单号", required = true),
            @ApiImplicitParam(paramType = "query", name = "tradeNo", value = "交易流水号", required = true),
    })
    @PostMapping(value = "getOrderTradeRecordByTradeNo")
    public Rest getOrderTradeRecordByTradeNo(@NotNull String orderCode, @NotNull String tradeNo) {
        boolean result = orderInfoService.getOrderTradeRecordByTradeNo(orderCode, tradeNo);

        if(result){
            return RestUtil.success();
        }else{
            return RestUtil.error();
        }
    }

    @ApiOperation(value = "泊链判断是否无感抬杆")
    @PostMapping(value = "verifyNosencePay")
    public Map<String,Object> verifyNosencePay(@RequestBody String data) {
        /**
         * 1、如果是月租卡，则回复支持，没有月卡，但是有余额，回复支持
         * 2、判断后泊链做支付功能，然后走“无感支付通知”接口
         * 3、如果出场时没产生费用，则不通知此接口
         * 4、入场时调用，是为了是否给车场通知，车场收到支付无感时，出场才会调用无感
         * */
        Map<String, Object> map = orderInfoService.verifyNosencePay(data);

        return map;
    }

    @ApiOperation(value = "非泊链出场判断是否无感抬杆")
    @PostMapping(value = "car-out-pay")
    public Map<String,Object> carOutPay(@RequestBody String data) {
        /**
         * 1、如果是月租卡，则直接抬杆
         * 2、如果不是月租卡，但是有余额，则扣除余额后抬杆
         * 3、道尔、盒子等请求此接口
         * */
        Map<String, Object> map = orderInfoService.carOutPay(data);

        return map;
    }

    @ApiOperation(value = "泊链无感支付通知")
    @PostMapping(value = "noFeelOutParkNotice")
    public Map<String,Object> noFeelOutParkNotice(@RequestBody String data) {
        /**
         * 1、如果接口“泊链判断是否无感抬杆（verifyNosencePay）"响应支持，则泊链将支付结果通知此接口
         * 2、如果是
         */

        Map<String, Object> map = orderInfoService.noFeelOutParkNotice(data);

        return map;
    }

    @ApiOperation(value = "车辆出场通知")
    @PostMapping(value = "carOutPark")
    public Map<String,Object> carOutPark(@RequestBody String data) {
        /**
         * 1、如果历史订单为空，并且出场支付为0，则出场支付方式为未支付或原停车场会员卡
         * 2、连续4天支付是指每天会在车场的第1笔支付中取一个地址，取一个用户的地址，然后4天的数据出来之后，会没比对每两个地址之间的距离，如果精度都小于50米的话，就认为定位是正确的，就会更新车场的数据
         * 3、车主与车场union_id相同，则不通知
         */

        Map<String, Object> map = orderInfoService.carOutPark(data);

        /*向移动端发送进场消息*/
        if(map.get("customerId") != null){
            websocketUtil.sendMessage(map.get("customerId").toString(), "car-out-park@" + map.get("carNumber"));
        }

        return map;
    }

    @ApiOperation(value = "验证是否显示预离场按钮")
    @PostMapping(value = "verifyDisplayPrePayButton")
    public Rest verifyDisplayPrePayButton(@NotNull Long parkId,@NotNull String carNumber) {
       Boolean result  = orderInfoService.verifyDisplayPrePayButton(parkId,carNumber);
        if(result){
            return RestUtil.success();
        }else{
            return RestUtil.error();
        }
    }

}

